"""

Template module for Exits

Copy this module up one level and name it as you like, then
use it as a template to create your own Exits.

To make the default commands (such as @dig/@open) default to creating exits
of your new type, change settings.BASE_EXIT_TYPECLASS to point to
your new class, e.g.

settings.BASE_EXIT_TYPECLASS = "game.gamesrc.objects.myexit.MyExit"

Note that objects already created in the database will not notice
this change, you have to convert them manually e.g. with the
@typeclass command.

"""
from ev import Exit, Command, CmdSet, utils
from game.gamesrc.objects.object import MyObject

class MyExit(MyObject, Exit):
    """
    Exits are connectors between rooms. Exits are normal Objects except
    they defines the 'destination' property. It also does work in the
    following methods:

     basetype_setup() - sets default exit locks (to change, use at_object_creation instead)
     at_cmdset_get() - this auto-creates and caches a command and a command set on itself
                     with the same name as the Exit object. This
                     allows users to use the exit by only giving its
                     name alone on the command line.
     at_failed_traverse() - gives a default error message ("You cannot
                            go there") if exit traversal fails and an
                            attribute err_traverse is not defined.

    Relevant hooks to overload (compared to other types of Objects):
    at_before_traverse(traveller) - called just before traversing
    at_after_traverse(traveller, source_loc) - called just after traversing
    at_failed_traverse(traveller) - called if traversal failed for some reason. Will
                                    not be called if the attribute 'err_traverse' is
                                    defined, in which case that will simply be echoed.
    """
    def create_exit_cmdset(self, exidbobj):
        """
        Helper function for creating an exit command set + command.

        The command of this cmdset has the same name as the Exit object
        and allows the exit to react when the player enter the exit's name,
        triggering the movement between rooms.

        Note that exitdbobj is an ObjectDB instance. This is necessary
        for handling reloads and avoid tracebacks if this is called while
        the typeclass system is rebooting.
        """
        class ExitCommand(Command):
            """
            This is a command that simply cause the caller
            to traverse the object it is attached to.
            """
            locks = "cmd:all()" # should always be set to this.
            obj = None
            arg_regex=r"\s.*?|$"
            is_exit = True      # this helps cmdhandler disable exits in cmdsets with no_exits=True.

            def func(self):
                "Default exit traverse if no syscommand is defined."
                self.obj.at_before_traverse(self.caller)
                if self.obj.access(self.caller, 'traverse'):
                    # we may traverse the exit.
                    self.obj.at_traverse(self.caller, self.obj.destination)
                else:
                    # exit is locked
                    if self.obj.db.err_traverse:
                        # if exit has a better error message, let's use it.
                        self.caller.msg(self.obj.db.err_traverse)
                    else:
                        # No shorthand error message. Call hook.
                        self.obj.at_failed_traverse(self.caller)

        # create an exit command.
        cmd = ExitCommand()
        cmd.key = exidbobj.db_key.strip().lower()
        cmd.obj = exidbobj
        cmd.aliases = exidbobj.aliases
        cmd.locks = str(exidbobj.locks)
        cmd.destination = exidbobj.db_destination
        cmd.auto_help = False
        # create a cmdset
        exit_cmdset = CmdSet(None)
        exit_cmdset.key = '_exitset'
        priority = 20
        exit_cmdset.duplicates = True
        directions = ['north', 'south', 'west', 'east', 'up', 'down']
        if cmd.key in directions:
            priority += directions.index(cmd.key)
        exit_cmdset.priority = priority
        # add command to cmdset
        exit_cmdset.add(cmd)
        return exit_cmdset


    # Command hooks
    def at_object_creation(self):
        """
        Setup exit-security
        """
        super(MyExit, self).at_object_creation()
        self.locks.add("call:compare_attr(wild_loc)")
        self.db.wild_dest = (None, None)
        self.db.desc = ""

    def at_before_traverse(self, traversing_object):
        """
        Called just before an object uses this object to
        traverse to another object (i.e. this object is a type of Exit)

        The target location should normally be available as self.destination.
        """
        if hasattr(self, "wild_dest"):
            traversing_object.db.wild_loc = self.db.wild_dest



    def at_failed_traverse(self, traversing_object):
        """
        This is called if an object fails to traverse this object for some
        reason. It will not be called if the attribute "err_traverse" is defined,
        that attribute will then be echoed back instead as a convenient shortcut.

        (See also hooks at_before_traverse and at_after_traverse).
        """
        traversing_object.msg("Non puoi andare li'.")


    def return_appearance(self, pobject):
        """
        This is a convenient hook for a 'look'
        command to call.
        """
        if not pobject:
            return
        translation = {"north": "nord",
                       "south": "sud",
                       "east": "est",
                       "west": "ovest",
                       "up": "l'alto",
                       "down": "il basso",
                       "in": "dentro",
                       "out": "fuori"}

        objname = self.name.lower()
        if not objname in translation:
            return super(MyExit, self).return_appearance(pobject)
        direction = translation[objname]
        string = "{cGuardi verso %s.{n" % direction
        desc = utils.fill(self.attr("desc"))
        if desc:
            string += "\n %s" % desc
        mobs, mobs_far = [], []
        def f(x):
            a = hasattr(x, "has_player") and x.has_player
            b = hasattr(x, "is_mob") and x.is_mob
            return a or b
        mobs = filter(f, self.destination.contents)
        mobs = [element.name for element in mobs]
        if len(mobs) == 1:
            string += "\nVedi %s in quella direzione." % mobs[0]
        elif len(mobs) > 1:
            string += "\nVedi %s e %s in quella direzione." % (", ".join(mobs[:-1]), mobs[-1:][0])
        exits = [element for element in self.destination.contents if element.destination]
        exits = filter(lambda x: x.name.lower() == objname, exits)
        if exits and not (hasattr(exits[0], "is_closed") and exits[0].is_closed):
            mobs_far = filter(f, exits[0].destination.contents)
            mobs_far = [element.name for element in mobs_far]
        
        if len(mobs_far) == 1:
            string += "\nVedi %s piu' in la' verso %s." % (mobs_far[0], direction)
        elif len(mobs_far) > 1:
            string += "\nVedi %s e %s piu' in la' verso %s." % (", ".join(mobs_far[:-1]), mobs_far[-1:][0], direction)

        if not mobs and not mobs_far:
            string += "\nNon vedi nessuno in quella direzione."
        return string
